<?php

	// +----------------------------------------------------------------------
	// | 图片模型--负责图片的上传.
	// +----------------------------------------------------------------------
	// | Copyright (c) 2015-2024 http://www.yicmf.com, All rights reserved.
	// +----------------------------------------------------------------------
	// | Author: 微尘 <yicmf@qq.com>
	// +----------------------------------------------------------------------

	namespace app\event\file;

	use app\common\event\Job;
	use app\event\file\QrCode as QrCodeEvent;
	use think\Exception;
	use think\exception\ValidateException;
    use think\facade\Env;
    use think\Image as ImageThink;
	use think\facade\Log;
	use think\File;
	use think\facade\Config;
	use app\model\file\Image as ImageModel;
	use app\model\ucenter\User as UserModel;
	use think\facade\Db;
	use yicmf\tools\FileOperation;

	class Image extends Common
	{



		public function zip1()
		{
			$files= ImageModel::where('id','>',150)->select();
			$setting = Config::get('upload_image');
			$fileOp = new FileOperation();
			$toDir = $setting['save_root'] . '/uploads/zip/'.time_format(time(), 'Ym/d');
			if (!is_dir($toDir)) {
				mkdir($toDir, 0755, true);
			}
			$zip = new \ZipArchive;
			if ($zip->open($toDir.'/test_new.zip', \ZipArchive::CREATE) === true)
			{
				foreach ($files as $file) {
					$path = $setting['save_root'] . $file['path'];
					$basename = pathinfo($path)['basename'];
//					$zip->addFile($path,$toDir.'/'.$basename);
					$zip->addFile($path,$basename);
//					dump(copy($path,$toDir.'/'.$basename));
//				dump(is_file($path));
				}

				// 将指定文件添加到zip中
//				$zip->addFile('test.txt');

				// test.txt文件添加到zip并将其重命名为newfile.txt
//				$zip->addFile('test.txt', 'newfile.txt');

				// 将test.txt文件添加到zip文件中的test文件夹内
//				$zip->addFile('test.txt', 'test/newfile.txt');

				//将一个空的目录添加到zip中
//				$zip->addEmptyDir ('test');

//				// 将有指定内容的new.txt文件添加到zip文件中
//				$zip->addFromString('new.txt', '要添加到new.txt文件中的文本');
//
//				// 将有指定内容的new.txt添加到zip文件中的test文件夹
//				$zip->addFromString('test/new.txt', '要添加到new.txt文件中的文本');

				//将images目录下所有文件添加到zip中
//				if ($handle = opendir('images')){
//					// 添加目录中的所有文件
//					while (false !== ($entry = readdir($handle))){
//						if ($entry != "." && $entry != ".." && !is_dir('images/' . $entry)){
//							$zip->addFile('images/' . $entry);
//						}
//					}
//					closedir($handle);
//				}

				// 关闭zip文件
				$zip->close();
			}

		}

		public static function getUrl($id, $preview = 'preview')
		{
			if (is_numeric($id) && $id > 0) {
				$pic = ImageModel::find($id);
				if ($pic) {
					return $pic['url'];
				} else {
					return '/static/common/images/default_image_240.gif';
				}
			} elseif (!$id) {
				return '/static/common/images/default_image_240.gif';
			} else {
				return $id;
			}
		}

		/**
		 * 删除资源
		 * @param      $param
		 * @param      $user
		 * @return mixed
		 * @author  : 微尘 <yicmf@qq.com>
		 * @datetime: 2019/1/29 20:10
		 */
		public function delete($param, $user = null)
		{
			$image = ImageModel::where('user_id', $user['id'])->where('id', $param['id'])->find();
			if ($image) {
				$image['status'] = -2;
				$image->save();
				// 删除文件
//                    $ext = '.' . pathinfo($image['save_name'], PATHINFO_EXTENSION);
//                    $basename = basename($image['save_name'], $ext);
//                    $this->_deleteFile($image, $basename, $ext, 'original');
//                    $this->_deleteFile($image, $basename, $ext, 1280);
//                    $this->_deleteFile($image, $basename, $ext, 360);
//                    $this->_deleteFile($image, $basename, $ext, 240);
//                    $this->_deleteFile($image, $basename, $ext, 60);
				// 删除对应文件
				$data['code'] = 0;
				$data['message'] = '删除成功';
			} else {
				$data['code'] = 1;
				$data['message'] = '资源不存在';
			}
			return $data;
		}

		protected function _deleteFile($image, $basename, $ext, $width)
		{
			$path = str_replace($image['save_name'], $basename . '_' . $width . $ext, $image->getData('path'));
			if (is_file($path)) {
				@unlink($path);
			}
			// 七牛的也删除，默认保留30天
			if ('qiniu' == $image['driver'] && 'original' != $width) {
				$setting = Config::get('upload_image');
				// 构建鉴权对象
				$auth = new QuniuAuth($setting['qiniu_access_key'], $setting['qiniu_secrect_key']);
				$key = str_replace($image['save_name'], $basename . '_' . $width . $ext, $image->getData('url'));
				$config = new \Qiniu\Config();
				$bucketManager = new BucketManager($auth, $config);
				// 上传到七牛后保存的文件名
				$key = ltrim($key, '/');
				$bucketManager->delete($setting['qiniu_bucket'], $key);
				//                $bucketManager->deleteAfterDays($setting['qiniu_bucket'], $key, 30);
			}
		}

		public static function info($id, $field = 'url')
		{
			$image = ImageModel::find($id);
			if ($image) {
				return $image[$field];
			} else {
				return ' ';
			}
		}

		/**
		 * @param $str
		 * @param $wechat_media_id
		 * @param $url
		 * @return array
		 * @throws Exception
		 * @author  : 微尘 <yicmf@qq.com>
		 * @datetime: 2019/1/15 17:22
		 */
		public function uploadByMaterial($str, $wechat_media_id, $url)
		{
			$file = ImageModel::where('wechat_media_id', $wechat_media_id)->find();
			if ($file) {
				$result = [
					'code' => 0,
					'data' => $file
				];
				return $result;
			}
			$filename = uniqid() . '.png';
			// 检查路径是否存在，如不存在则创建
			$dir = app()->getRootPath() . 'public/uploads/image/' . time_format(time(), 'Y/m/d/');
			$dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
			if (!is_dir($dir)) {
				//第三个参数是“true”表示能创建多级目录，iconv防止中文目录乱码
				mkdir(iconv("UTF-8", "GBK", $dir), 0777, true);
			}
			$resource = fopen($dir . $filename, 'a');
			fwrite($resource, $str);
			fclose($resource);
			$file = new File($dir . $filename);
			$data = [];
			$data['md5'] = $file->hash('md5');
			$data['wechat_url'] = $url;
			$data['wechat_media_id'] = $wechat_media_id;
			$data['sha1'] = $file->hash('sha1');
			//        $data['driver'] = $setting['driver'];
			$data['name'] = $file->getInfo('name');
			$data['remark'] = $file->getInfo('name');
			$data['size'] = $file->getInfo('size');
			$data['mime'] = $file->getMime();
			$data['path'] = $dir . $filename;
			$data['ext'] = pathinfo($data['path'], PATHINFO_EXTENSION);
			$data['save_name'] = pathinfo($data['path'], PATHINFO_BASENAME);
			$data['save_path'] = pathinfo($data['path'], PATHINFO_DIRNAME);
			$image = ImageModel::create($data);
			if (!$image) {
				throw new Exception('保存图片信息失败');
			}
			$result = [
				'code' => 0,
				'data' => $image
			];
			return $result;
		}

		public function uploadUrl($url)
		{
			$path = $this->downLoad_pic($url);
			$file = new File($path);
			$data = [];
			$data['md5'] = $file->hash('md5');
			$data['wechat_url'] = $url;
			$data['sha1'] = $file->hash('sha1');
			//        $data['driver'] = $setting['driver'];
			$data['name'] = $file->getInfo('name');
			$data['remark'] = $file->getInfo('name');
			$data['size'] = $file->getInfo('size');
			$data['mime'] = $file->getMime();
			$data['path'] = $path;
			$data['ext'] = pathinfo($path, PATHINFO_EXTENSION);
			$data['save_name'] = pathinfo($path, PATHINFO_BASENAME);
			$data['save_path'] = pathinfo($path, PATHINFO_DIRNAME);
			$image = ImageModel::create($data);
			if (!$image) {
				throw new Exception('保存图片信息失败');
			}
			$result = [
				'code' => 0,
				'data' => $image
			];
			return $result;
		}

		protected function downLoad_pic($url)
		{
			if ($url == "") {
				return false;
			}
			$filename = uniqid() . '.png';
			// 检查路径是否存在，如不存在则创建
			$dir = app()->getRootPath() . 'public/uploads/image/' . time_format(time(), 'Y/m/d/');
			$dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
			if (!is_dir($dir)) {
				//第三个参数是“true”表示能创建多级目录，iconv防止中文目录乱码
				mkdir(iconv("UTF-8", "GBK", $dir), 0777, true);
			}
			ob_start();
			readfile($url);
			$img = ob_get_contents();
			ob_end_clean();
			$fp2 = fopen($dir . $filename, "a");
			if (fwrite($fp2, $img) === false) {
				throw new Exception('无法写入图片');
			}
			fclose($fp2);
			return $dir . $filename;
		}

		/**
		 * 文件上传.
		 * @param array $param post信息
		 * @param File $file 要上传的文件列表（需要使用request获取的请求）
		 * @param UserModel $user 是否为编辑器
		 * @param integer $is_editor 是否为编辑器
		 * @return array 文件上传成功后的信息
		 * @author 微尘 <yicmf@qq.com>
		 */
		public function upload($param, $file, $user = null, $is_editor = 0): array
		{
			try {
				if (!is_object($file)) {
					// 上传失败获取错误信息
					throw new Exception('上传信息错误');
				}
				// 检测文件是否存在
				$image = ImageModel::where('md5', $file->hash('md5'))->where('status', 1)->find();
				if (!$this->checkImage($image)) {
					/* 图片预处理 --- 上传文件 */
					$data = $this->_dealUpload($file, $is_editor);
					$user && $data['user_id'] = $user['id'];
					$data = array_merge($data, $this->distinguish($param, $data));
					$image = ImageModel::create($data);
					if (!$image) {
						throw new Exception('保存图片信息失败');
					}
					// 同步cdn
					if ($data['driver'] !== 'local') {
						Job::addTask('sync_image_cdn', ['image_id' => $image['id'], 'param' => $param]);
					}
				} else {
					// 复制一份
					$image = $image->toArray();
					if ($user && $image['user_id'] != $user['id']) {
						$image['user_id'] = $user['id'];
						unset($image['id']);
						$image = ImageModel::create($image);
					}
				}

				$result['code'] = 0;
				$result['data'] = $image;
			} catch (Exception $e) {
				$result['code'] = 1;
				$result['message'] = $e->getMessage();
				$result['file'] = $e->getFile();
				$result['line'] = $e->getLine();
			}
			return $result;
		}

		/**
		 * 检查图片是否存在
		 * @param $image
		 * @return bool
		 */
		public function checkImage($image): bool
		{
			if ($image) {
				if (is_file($image['path'])) {
					return true;
				} else {
					// 删除模型
					$image->delete();
				}
			}
			return false;
		}

		/**
		 * 图片上传处理
		 * @param File $file
		 * @param int $is_editor
		 * @return array
		 * @throws Exception
		 * @author  : 微尘 <yicmf@qq.com>
		 */
		protected function _dealUpload(File $file, int $is_editor = 0): array
		{
			$setting = config('upload_image');
			$uploadDir = '';
			$save_data = $this->_formatInfo($file, $setting, $uploadDir);
			try {
				$setting['max_size'] != 0 && $validate['fileSize'] = $setting['max_size'] * 1024 * 1024;
//				$validate['fileExt'] = $setting['ext'];
				$validate['fileMime'] = $setting['mimes'];
//				$validate['image'] = $setting['mimes'];
				validate(['image' => $validate])->check(['image' => $file]);
			} catch (ValidateException $e) {
				// 验证失败 输出错误信息
				throw new Exception($e->getError());
			}
			$save_data['has_original'] = $setting['has_original'];
			$save_data['has_thumbnail'] = $setting['has_thumbnail'];
			$image = ImageThink::open($file);

			$file_name = pathinfo($save_data['save_name'])['filename'];
			if (1 == $setting['has_original']) {
				$result = $image->save($uploadDir . $file_name . '_original' . '.' . $save_data['ext']);
				if (!$result) {
					throw new Exception('图片保存失败');
				}
			}
			// 是否开启水印
			if ($setting['water_type'] == 2)
			{
				$image = $image->text($setting['text_content'],
                    root_path() .'data'. DIRECTORY_SEPARATOR. $setting['font_file'],
					$setting['text_size'], $setting['text_color'], $setting['text_location_id'], [$setting['text_water_dx'], $setting['text_water_dy']],
					$setting['text_angle']);
			}elseif ( $setting['water_type'] == 1)
			{
				if ($image->width() >= $setting['water_mini_width']) {
					$source = public_path(). 'static' . DIRECTORY_SEPARATOR . 'common/images/' . $setting['water_image'];
					$image = $image->water($source, $setting['image_location_id'], $setting['water_transparency']);
				}
			}
			$result = $image->save($uploadDir .$file_name . '.' . $save_data['ext']);
			if (!$result) {
				throw new Exception('图片保存失败');
			}
			// 保存原图
			if ($save_data['has_thumbnail']) {
				$thumbnail_size = explode(',', $setting['thumbnail_size']);
				foreach ($thumbnail_size as $item) {
					$name = $image->save($uploadDir . $file_name. '_' . $item . '.' . $save_data['ext']);;
//					$image->save($name);
				}
			}
			return $save_data;
		}

		/**
		 * 同步图片到CDN
		 * @param $data
		 * @return string
		 */
		public function syncCdn($data)
		{
			$setting = Config::get('upload_image');
			// 数据迁移到七牛
			if ('qiniu' == $setting['driver']) {
				// 构建鉴权对象
				// 构建鉴权对象
				$auth = new QuniuAuth($setting['qiniu_access_key'], $setting['qiniu_secrect_key']);
				// 生成上传 Token
				$token = $auth->uploadToken($setting['qiniu_bucket']);
				$image = ImageModel::find($data['image_id']);
				$ext = '.' . pathinfo($image['save_name'], PATHINFO_EXTENSION);
				$basename = basename($image['save_name'], $ext);
				// 初始化 UploadManager 对象并进行文件的上传。
				$uploadMgr = new QiniuUploadManager();
				list($result, $err) = self::_uploadQiniu($image, $basename, $ext, 1280, $uploadMgr, $token);
				//                $image['hash'] = $result['hash'];
				if ($err !== null) {
					Log::write('七牛迁移错误：' . var_export($err, true));
				}
				self::_uploadQiniu($image, $basename, $ext, 360, $uploadMgr, $token);
				self::_uploadQiniu($image, $basename, $ext, 240, $uploadMgr, $token);
				self::_uploadQiniu($image, $basename, $ext, 60, $uploadMgr, $token);
				$image['driver'] = 'qiniu';
				$image->save();
				return 'success';
			} else {
				return 'fail';
			}
		}

		/**
		 * 执行上传到七牛
		 * @param $image
		 * @param $basename
		 * @param $ext
		 * @param $width
		 * @param $uploadMgr
		 * @param $token
		 * @return bool
		 * @author  : 微尘 <yicmf@qq.com>
		 * @datetime: 2019/1/29 18:25
		 */
		protected static function _uploadQiniu($image, $basename, $ext, $width, $uploadMgr, $token)
		{
			$key = str_replace($image['save_name'], $basename . '_' . $width . $ext, $image->getData('url'));
			// 要上传文件的本地路径
			$path = str_replace($image['save_name'], $basename . '_' . $width . $ext, $image->getData('path'));
			if (is_file($path)) {
				// 上传到七牛后保存的文件名
				$key = ltrim($key, '/');
				// 调用 UploadManager 的 putFile 方法进行文件的上传。
				return $uploadMgr->putFile($token, $key, $path);
			} else {
				return false;
			}
		}

		/**
		 * 解析信息
		 * @param array $param
		 * @param array $data
		 * @return mixed
		 * @throws Exception
		 * @author 微尘 <yicmf@qq.com>
		 */
		protected function distinguish(array $param, array $data)
		{
			if (!Config::get('aibaidu.open')) {
				return [];
			}
			if (isset($param['type']) && 'idcard' == $param['type']) {
				// 调用身份证识别
				// 调用通用文字识别, 图片参数为本地图片
//				$data['type'] = 'idcard';
				$image = file_get_contents($data['path']);
				include app()->getRootPath() . 'extend/aibaidu/AipOcr.php';
				// 百度识别信息
				$client = new \AipOcr(Config::get('aibaidu.app_id'), Config::get('aibaidu.app_key'), Config::get('aibaidu.secret_key'));
				$idCardSide = isset($param['side']) ? $param['side'] : 'front';
				// 如果有可选参数
				$options = [];
				$options['detect_direction'] = 'true';
				$options['detect_risk'] = 'true';
				$result = $client->idcard($image, $idCardSide, $options);
				if ($result)
					if ('normal' != $result['image_status']) {
						$tips = [
							'reversed_side' => '身份证正反面颠倒',
							'non_idcard' => '上传的图片中不包含身份证',
							'blurred' => '身份证模糊',
							'other_type_card' => '其他类型证照',
							'over_exposure' => '身份证关键字段反光或过曝',
							'unknown' => '未知状态',
						];
						throw new Exception($tips[$result['image_status']]);
					} else {
						if ('front' == $idCardSide) {
							$data['info'] = [
								'address' => $result['words_result']['住址']['words'],
								'birthday' => $result['words_result']['出生']['words'],
								'name' => $result['words_result']['姓名']['words'],
								'idcard_no' => $result['words_result']['公民身份号码']['words'],
								'sex' => $result['words_result']['性别']['words'],
								'nation' => $result['words_result']['民族']['words'],
							];
						} else {
							$data['info'] = [
								'start_time' => $result['words_result']['签发日期']['words'],
								'end_time' => $result['words_result']['失效日期']['words'],
								'address' => $result['words_result']['签发机关']['words'],
							];
						}
					}
			} elseif (isset($param['type']) && 'hand' == $param['type']) {
				if (empty($param['front_id'])) {
					throw new Exception('没有发现对比图片');
				}
				$idCardFrand = ImageModel::get($param['front_id']);
				if (!is_file($idCardFrand['path'])) {
					throw new Exception('没有发现对比图片');
				}
				include app()->getRootPath() . 'extend/aibaidu/AipFace.php';
				$client = new \AipFace(Config::get('aibaidu.app_id'), Config::get('aibaidu.app_key'), Config::get('aibaidu.secret_key'));
				$result = $client->match([
					[
						'image' => base64_encode(file_get_contents($idCardFrand['path'])),
						'face_type' => 'CERT',
						'image_type' => 'BASE64'
					],
					[
						'image' => base64_encode(file_get_contents($data['path'])),
						'image_type' => 'BASE64',
						'liveness_control' => 'HIGH'
					]
				]);
				if (isset($result['error_code']) && 0 != $result['error_code']) {
					$tips = [
						'the second image liveness check fail' => '活体检测未通过',
						'liveness check fail' => '活体检测未通过',
						'pic not has face' => '图片中没有人脸',
						'image check fail' => '无法解析人脸',
					];
					$result['error_msg'] = isset($tips[$result['error_msg']]) ? $tips[$result['error_msg']] : $result['error_msg'];
					$result['error_msg'] = $result['error_msg'] . '，如果您确认信息无误，可以提交人工审核';
					$result['code'] = 1;
				} else {
					//face_list [] score
					$result = $result['result'];
					// 两个人脸及得分
					if (Config::get('aibaidu.face_score') > $result['score']) {
						$result['error_msg'] = '匹配度不足，请重新拍照审核，如果您确认信息无误，可以提交人工审核';
						$result['code'] = 1;
					} else {
						$result['code'] = 0;
					}
				}
				$data['info'] = $result;
			} elseif (isset($param['type']) && 'license' == $param['type']) {
				// 营业执照
				include app()->getRootPath() . 'extend/aibaidu/AipOcr.php';
				$client = new \AipOcr(Config::get('aibaidu.app_id'), Config::get('aibaidu.app_key'), Config::get('aibaidu.secret_key'));
				$image = file_get_contents($data['path']);
				// 调用营业执照识别
				$result = $client->businessLicense($image);
				if (isset($result['error_code']) && 0 != $result['error_code']) {
					throw new Exception($result['error_msg']);
				} else {
					$result = $result['words_result'];
					$info = [];
					if (isset($result['社会信用代码'])) {
						$info['store_social_credit_code'] = $result['社会信用代码']['words'];
					}
					if (isset($result['单位名称'])) {
						$info['store_name'] = $result['单位名称']['words'];
					}
					if (isset($result['法人'])) {
						$info['store_legal_person'] = $result['法人']['words'];
					}
					if (isset($result['证件编号'])) {
						$info['store_no'] = $result['证件编号']['words'];
					}
					if (isset($result['成立日期'])) {
						$info['store_start_time'] = $result['成立日期']['words'];
					}
					if (isset($result['地址'])) {
						$info['store_address'] = $result['地址']['words'];
					}
					if (isset($result['有效期'])) {
						$info['store_effective_date'] = $result['有效期']['words'];
					}
					$data['info'] = $info;
				}
			} elseif (isset($param['type']) && 'qrcode' == $param['type']) {

				$info = QrCodeEvent::read($data);
				if (0 != $info['code']) {
					throw new Exception($info['message']);
				}
				$data['info'] = $info;
			}
//			if (isset($param['module']) && 'wechat' == $param['module']) {
//				// 微信模块上传，则同步到公众号
//				$media = new MediaOfficial();
//				$result = $media->uploadimg($data['path'], $data['save_name']);
//				if (isset($result['url'])) {
//					$data['wechat_url'] = $result['url'];
//				}
//			}
			return $data;
		}


	}
